// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "intangiblesentry.h"
#include "ui_intangiblesentry.h"

#include "receiverequestdialog.h"
#include "ui_receiverequestdialog.h"
#include "useful.h"

#include "addressbookpage.h"
#include "addresstablemodel.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "walletmodel.h"
#include "guiconstants.h"

#include <QApplication>
#include <QClipboard>

IntangiblesEntry::IntangiblesEntry(QWidget *parent) :
    QStackedWidget(parent),
    ui(new Ui::IntangiblesEntry),
    model(0)
{
    ui->setupUi(this);

    setCurrentWidget(ui->Intangibles);

#ifdef Q_OS_MAC
    ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
    ui->payTo->setPlaceholderText(tr("Enter payee's IPCoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
ui->payeePubkey->setPlaceholderText(tr("Enter payee's public key (e.g. 02f62fcc43d955b095f393ce0f25a1b7165816ff81aa6e350a4a97da85e09fc0d4)"));
ui->conditionalString->setPlaceholderText(tr("Enter conditional (e.g. patent US2014123456 granted by 20160101)"));
#endif
    setFocusProxy(ui->payTo);

    // normal ipcoin address field
    GUIUtil::setupAddressWidget(ui->payTo, this);
    // just a label for displaying ipcoin address(es)
    ui->payTo_is->setFont(GUIUtil::bitcoinAddressFont());
}

IntangiblesEntry::~IntangiblesEntry()
{
    delete ui;
}

void IntangiblesEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void IntangiblesEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSelection, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void IntangiblesEntry::on_payTo_textChanged(const QString &address)
{
    updateLabel(address);
}

void IntangiblesEntry::setModel(WalletModel *model)
{
    this->model = model;

    if (model && model->getOptionsModel())
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

    connect(ui->payAmount, SIGNAL(textChanged()), this, SIGNAL(payAmountChanged()));
    clear();
}

void IntangiblesEntry::clear()
{
    // clear UI elements for normal payment
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
ui->payeePubkey->clear();
ui->conditionalString->clear();
    // clear UI elements for insecure payment request
    ui->payTo_is->clear();
    ui->memoTextLabel_is->clear();
    ui->payAmount_is->clear();
    // clear UI elements for secure payment request
    ui->payTo_s->clear();
    ui->memoTextLabel_s->clear();
    ui->payAmount_s->clear();

    // update the display unit, to not use the default ("IPC")
    updateDisplayUnit();
}

void IntangiblesEntry::on_pushButton_clicked()
{
AddressBookPage dlg(AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this);
    dlg.setModel(model->getAddressTableModel());
    dlg.exec();
QString address;
    QString label;
address = dlg.getReturnValue();
SendCoinsRecipient info(address, label,0, "");
std::string result = executeRPCcommand(QString::fromStdString("validateaddress "+ address.toStdString()));
result = getRPCvalue(result,"pubkey");
    ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
    dialog->setAttribute(Qt::WA_DeleteOnClose);

dialog->pubkey = result;
    dialog->setModel(model->getOptionsModel());
    dialog->setInfo(info, result);
    dialog->show();
}

void IntangiblesEntry::deleteClicked()
{
    emit removeEntry(this);
}

bool IntangiblesEntry::validate()
{
    if (!model)
        return false;

    // Check input validity
    bool retval = true;

    // Skip checks for payment request
    if (recipient.paymentRequest.IsInitialized())
        return retval;

    if (!ui->payTo->hasAcceptableInput() || !model->validateAddress(ui->payTo->text()))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

/////////check pubkey consistent with address. we don't need user to enter both
/////////as we can generate the address from pubkey, but this saves errors
std::string testkey = ui->payeePubkey->text().toStdString();
std::vector<unsigned char> keyvec(testkey.begin(), testkey.end());
CPubKey pk;// = new CPubKey();

//The following code converts the string testkey to its byte-by-bytes
unsigned char byt;
unsigned char val;
for (int i = 0; i < 66; i+=2)
{ 
if (testkey[i]>96)
{
val = testkey[i] - 'W';
}
else { val = testkey[i] - '0'; }
byt = val*16; 

if (testkey[i+1]>96)
{
val = testkey[i+1] - 'W';
}
else { val = testkey[i+1] - '0'; }

byt += val;
pk.vch[i/2] = (unsigned int)byt;
 }
//pk = CPubKey(keyvec);
CKeyID id = pk.GetID();
testkey = CBitcoinAddress(id).ToString();

cout << testkey << endl;
//cout << ui->payTo->text().toStdString() << endl;
if (ui->payTo->text().toStdString() != testkey)
{
ui->payTo->setValid(false);
ui->payeePubkey->setStyleSheet(STYLE_INVALID);
retval = false;
QMessageBox msgBox;
msgBox.setWindowTitle("Error");
msgBox.setText("Payee's public key does not match their address");
 msgBox.setStandardButtons(QMessageBox::Cancel);
 msgBox.setDefaultButton(QMessageBox::Cancel);
msgBox.exec();
}



    if (!ui->payAmount->validate())
    {
        retval = false;
    }

if (ui->payeePubkey->text().isEmpty())
{
ui->payeePubkey->setStyleSheet(STYLE_INVALID);
retval = false;
}

if (ui->conditionalString->text().isEmpty())
{
ui->conditionalString->setStyleSheet(STYLE_INVALID);
retval = false;
}

    // Reject dust outputs:
    if (retval && GUIUtil::isDust(ui->payTo->text(), ui->payAmount->value())) {
        ui->payAmount->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient IntangiblesEntry::getValue()
{
    // Payment request
    if (recipient.paymentRequest.IsInitialized())
        return recipient;

    // Normal payment
    recipient.address = ui->payTo->text();
    recipient.label = ui->addAsLabel->text();
    recipient.amount = ui->payAmount->value();

    return recipient;
}

string IntangiblesEntry::getPayeepubkey()
{
	return ui->payeePubkey->text().toStdString();
}
string IntangiblesEntry::getConditional()
{
    return ui->conditionalString->text().toStdString();
}

QWidget *IntangiblesEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addAsLabel);
    QWidget *w = ui->payAmount->setupTabChain(ui->addAsLabel);
    QWidget::setTabOrder(w, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    return ui->addressBookButton;
}

void IntangiblesEntry::setValue(const SendCoinsRecipient &value)
{
    recipient = value;

    if (recipient.paymentRequest.IsInitialized()) // payment request
    {
        if (recipient.authenticatedMerchant.isEmpty()) // insecure
        {
            ui->payTo_is->setText(recipient.address);
            ui->memoTextLabel_is->setText(recipient.message);
            ui->payAmount_is->setValue(recipient.amount);
            ui->payAmount_is->setReadOnly(true);
            setCurrentWidget(ui->Intangibles_InsecurePaymentRequest);
        }
        else // secure
        {
            ui->payTo_s->setText(recipient.authenticatedMerchant);
            ui->memoTextLabel_s->setText(recipient.message);
            ui->payAmount_s->setValue(recipient.amount);
            ui->payAmount_s->setReadOnly(true);
            setCurrentWidget(ui->Intangibles_SecurePaymentRequest);
        }
    }
    else // normal payment
    {
        ui->payTo->setText(recipient.address);
        ui->addAsLabel->setText(recipient.label);
        ui->payAmount->setValue(recipient.amount);
    }
}

void IntangiblesEntry::setAddress(const QString &address)
{
    ui->payTo->setText(address);
    ui->payAmount->setFocus();
}

bool IntangiblesEntry::isClear()
{
    return ui->payTo->text().isEmpty() && ui->payTo_is->text().isEmpty() && ui->payTo_s->text().isEmpty();
}

void IntangiblesEntry::setFocus()
{
    ui->payTo->setFocus();
}

void IntangiblesEntry::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update payAmount with the current unit
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
        ui->payAmount_is->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
        ui->payAmount_s->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}

bool IntangiblesEntry::updateLabel(const QString &address)
{
    if(!model)
        return false;

    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
    {
        ui->addAsLabel->setText(associatedLabel);
        return true;
    }

    return false;
}
